"use strict";

var uk = require('./def.js');

/** 创建一个房间
 * station:关卡
 */
uk.create_room=function(id,name,station){
    var room = {
        id:id,
        name:name == null?station.name:name,
        station:station,
        status:uk.room_status.NONE,
        whoturn:-1,
        /** 每回合超时时间，单位秒 */
        outcardtimeout:20
    };
    room.game_begin = function(){
        if(this.status == uk.room_status.INGAME){
            console.log('game has begin');
            return;
        }
        this.status = uk.room_status.INGAME;
        this.winner = [];
        for(var i in this.players){
            var r = this.players[i];
            if(r == null) continue;
            r.status = uk.player_status.PLAYING;
        }
        var msg = {
        }
        msg.cardnum=new Array(this.players.length);
        /** 给玩家生成随机的牌 */
        for(var i in this.players){
            var r = this.players[i];
            if(r == null) continue;
            r.dealcards = [];
            msg.cardnum[i] = 0;
            for(var _c in r.cards){
                for(var _n=0;_n<r.cards[_c];++_n){
                    /** 添加一张卡牌到随机位置 */
                    if(r.dealcards.length == 0)
                        r.dealcards.push(_c);
                    else
                        r.dealcards.splice(uk.rand(0,r.dealcards.length),0,_c);
                }
                msg.cardnum[i] += r.dealcards.length;
            }
        }
        this.broadcast(uk.netevents.GAMEBEGIN,msg);

        /** 每人发两张牌 */
        for(var i in this.players){
            r = this.players[i];
            if(r == null) continue;
            this.deal_card(r,4);
        }

        /** 尚未开始 */
        this.whoturn = -1;
        /** 随机顺序
         * 这里可以根据需要重新确定开始顺序，比如灵敏之类的
         */
        this.player_turn( this.next_turn(uk.rand(0,this.players.length)) );
    }

    room.game_end = function(){
        if(this.status != uk.room_status.INGAME){
            console.log('game not begin~');
            return;
        }
        if(this.timer != null){
            uk.stop_timer(this.timer);
            this.timer = null;
        }

        this.status = uk.room_status.GAMEEND;
        this.whoturn = -1;

        /**计算成绩 */
        this.calc_game_scores();

        /** 游戏结束 */
        this.broadcast(uk.netevents.GAMEEND,{});

        /** 清理数据 */
        console.log('game end',this.status,uk.room_status.GAMEEND);
        for(var i in this.players){
            var r = this.players[i];
            if(r == null) continue;
            /**如果有ai，需要停止ai */
            if(r.template.ai){
                r.template.ai.stop(r);                
            }
            /**全都离开，除了玩家 */
            if(uk.ismonster(r)){
                this.player_leave(r,true);
            }
        }
    }

    /** 开始信息 */
    room.player_start = function(nr){
        if(this.status == uk.room_status.INGAME){
            console.log('game has begin~');
            return;
        }
        nr.status = uk.player_status.READY;
        this.broadcast(uk.netevents.READY,{id:nr.id});
        var _allready = true;
        for(var i in this.players){
            var r = this.players[i];
            if(r == null || r.user != null && r.status != uk.player_status.READY){
                _allready = false;
                break;
            }
        }
        if(_allready){
            this.game_begin();
        }
    }

    /** 玩家进入 */
    room.player_enter = function(nr,seat){
        if(this.status == uk.room_status.INGAME){
            console.log('game has begin~');
            return;
        }
        if(nr.status & uk.player_status.OFFLINE){
            nr.status = nr.status & ~(global.player_status.OFFLINE);
            this.broadcast(uk.netevents.CUTBACK,{id:nr.id},nr);
            return;
        }
        var i = seat;
        if(seat < 0||seat >= this.players.length||this.players[seat] != null){
            i = -1;
            for(var _i in this.players){
                if(this.players[_i] == null){
                    i = _i;
                    break;
                }
            }
            if(i == -1){
                if(nr.user != null)
                    this.send(nr,uk.netevents.ENTERROOM,{success:false,msg:'房间已满，请换个房间'});
                return false;
            }
        }
        nr.seat = i;
        nr.room = this;

        /** 发送给其他玩家 */
        var entermsg = {id:nr.id,name:nr.user? nr.user.name:nr.name,roleid:nr.template.id,seat:nr.seat,props:nr.props,equips:nr.equips};
        this.broadcast(uk.netevents.OTHERENTER,entermsg);

        if(nr.user != null){
            this.send(nr,uk.netevents.ENTER,{success:true,seat:nr.seat});
            for(var _i in this.players){
                var r = this.players[_i];
                if(r != null){
                    /** 发送其他玩家的信息给新进来的 */
                    this.send(nr,uk.netevents.OTHERENTER,{id:r.id,name:r.user?r.user.info.name:r.name,roleid:r.template.id,seat:r.seat,props:r.props,equips:r.equips});
                }
            }
        }
        this.players[i] = nr;
        return true;
    }

    room.player_leave = function(r,nonotify){
        if(r.room != this)
            return;
        if(this.status == uk.room_status.INGAME){
            if(r.user){
                this.player_cutoff(r);
            }
            var remainp = false;
            for(var i in this.players){
                var _r = this.players[i];
                if(_r && _r.status == uk.player_status.PLAYING && !uk.ismonster(_r)){
                    remainp = true;
                    break;
                }
            }

            if(!remainp){
                console.log('game end,user offline and no playe in room:',r.name,this.status);
                this.game_end();
                return;
            }else{
                console.log('game has begin,user offline:',r.name);
                return false;
            }
        }

        /** 广播离开 */
        if(!nonotify)
            this.broadcast(uk.netevents.LEAVE,{success:true,id:r.id});
        
        /** 如果有ai，需要检测是不是有ai在工作，结束他 */
        if(r.template.ai){
            r.template.ai.stop(r);
        }

        this.players[r.seat] = null;
        r.seat = -1;
        r.status = uk.player_status.NONE;
        r.room = null;
        console.log('player_leave',r.name);

        /** 游戏结束，恢复属性，我们这里的机制采取一个较为公平的战斗环境 */
        var changer = uk.create_changer();
        r.reset();
        changer.set_props(r.props);
        if(!nonotify)
            this.send(r,uk.netevents.PROPCHANGE,{id:r.id,changed:changer.value()});
        return true;
    }

    room.player_cutoff=function(r){
        if(this.status != uk.room_status.INGAME){
            console.log('game not begin');
            this.player_leave(r);
            return;
        }
        r.status |= uk.player_status.OFFLINE;
        this.broadcast(uk.netevents.CUTOFF,{id:r.id});
    }

    room.send=function(r,msgid,msg){
        if(r.user && r.user.sock){
            r.user.sock.emit(msgid,msg);
        }
    }

    room.broadcast=function(msgid,msg,not=null){
        for(var i in this.players){
            var r = this.players[i];
            if(r != null && (not ==null||not.id != r.id))
                this.send(r,msgid,msg);
        }
    }

    /** 该谁出牌啦 */
    room.player_turn = function(seat){
        if(this.status != uk.room_status.INGAME){
            console.log('game not begin~');
            return;
        }
        if(this.timer){
            uk.stop_timer(this.timer);
            this.timer = null;
        }
        var msg = {};
        if(this.whoturn != -1){
            var changed=uk.create_changer();
            var r = this.players[this.whoturn];
            r.outcards.push.apply(r.outcards,this.deskcards);
            this.deskcards = [];
            r.on_action(uk.events.ROUND_END,uk.event_status.BEFORE,r,null,changed);
            r.on_action(uk.events.ROUND_END,uk.event_status.NOW,r,null,changed);
            r.on_action(uk.events.ROUND_END,uk.event_status.AFTER,r,null,changed);

            if(changed.changed())
                this.broadcast(uk.netevents.PROPCHANGE,{id:r.id,changed:changed.value()});

            if(r.template.ai != null) r.template.ai.stop(r);
        }
        this.whoturn = seat;
        var r = this.players[seat];
        var changed=uk.create_changer();
        console.log('---------------------------------------------------------------');
        console.log('round begin',r.name);
        if(!r.on_action(uk.events.ROUND_BEGIN,uk.event_status.BEFORE,r,null,changed)){
            /** 如果有变化，则需要通知其他人 */
            if(changed.changed())
                this.broadcast(uk.netevents.PROPCHANGE,{id:r.id,changed:changed.value()});
            /** 通知客户端跳过回合 */
            this.broadcast(uk.netevents.SKIPROUND,{id:r.id});
            /** 1秒后开始下一个，这一秒钟用来播放个动画啥的 */
            this.timer = uk.start_timer(1000,this.player_turn,this,this.next_turn(this.whoturn));
            return;
        }
        /** 每回合开始时将mp补充满 */
        if(r.props.mp < r.props.maxmp){
            uk.actions.change_props(r,r,{mp:r.props.maxmp-r.props.mp},changed);
        }
        r.on_action(uk.events.ROUND_BEGIN,uk.event_status.NOW,r,null,changed);

        /** 每回合发2张牌 */
        this.deal_card(r,2);

        r.on_action(uk.events.ROUND_BEGIN,uk.event_status.AFTER,r,null,msg.changed);

        if(changed.changed())
            this.broadcast(uk.netevents.PROPCHANGE,{id:r.id,changed:changed.value()});

        this.broadcast(uk.netevents.SETTURN,{turn:r.seat,timeout:this.outcardtimeout});
        /** 下一回合 */
        this.timer = uk.start_timer(this.outcardtimeout*1000,this.player_turn,this,this.next_turn(this.whoturn));
        if(r.template.ai != null){
            r.template.ai.on_turn(r);
        }
    }

    /** 给指定的人发牌 */
    room.deal_card = function(r,count){
        if(this.status != uk.room_status.INGAME){
            console.log('game not begin~');
            return;
        }
        var changed=uk.create_changer();
        if(!r.on_action(uk.events.DEAL_CARD,uk.event_status.BEFORE,null,changed)){
            this.broadcast(uk.netevents.SKIPDEAL,{id:r.id});
            console.log('deal card skip for:'+r.name);
            if(changed.changed())
                this.broadcast(uk.netevents.PROPCHANGE,{id:r.id,changed:changed.value()});
            return;
        }
        /** 发牌 */
        var msg = {};
        msg.id = r.id;
        msg.cards = [];
        var realcards = [];
        for(var i = 0;i < count;++i){
            if(r.dealcards.length > 0){
                var idx = uk.rand(0,r.dealcards.length);
                var c = r.dealcards[idx];
                r.dealcards.splice(idx,1);
                r.handcards.push(c);
                msg.cards.push(0);/** 其他人发牌背 */
                realcards.push(c);
            }
        }
        msg.remain = r.dealcards.length;
        r.on_action(uk.events.DEAL_CARD,uk.event_status.NOW,null,changed);
        this.broadcast(uk.netevents.DEALCARD,msg,r);
        if(r.user){
            msg.cards = realcards;
            this.send(r,uk.netevents.DEALCARD,msg);
        }
        if(changed.changed())
            this.broadcast(uk.netevents.PROPCHANGE,{id:r.id,changed:changed.value()});
    }

    room.next_turn = function(seat){
        var _seat = seat;
        for(var i in this.players){
            _seat=(_seat+1)%this.players.length;
            if(this.players[_seat] && this.players[_seat].props.hp>0)
                return _seat;
        }
        return seat;
    }
    
    room.next_turn = function(seat){
        var _seat = seat;
        for(var i in this.players){
            _seat=(_seat <= 0?this.players.length-1:_seat-1);
            if(this.players[_seat] && this.players[_seat].props.hp>0)
                return _seat;
        }
        return seat;
    }

    /**
     * 对谁出牌，targetid为对准目标的id
     */
    room.player_outcard = function(r,cid,targetid){
        if(this.status != uk.room_status.INGAME){
            console.log('game not begin~');
            return;
        }
        if(r.seat != this.whoturn){
            console.log('the turn is timeout -> '+r.name);
            return;
        }

        var cpos = -1;
        for(var i in r.handcards){
            var _c = r.handcards[i];
            if(_c == cid){
                cpos = i;
                break;
            }
        }

        if(cpos == -1){
            console.log('outcards failed on card not exist -> '+cid);
            return;
        }

        var c = uk.t_cards[cid];
        var target = null;
        if(uk.target_types.SELF == c.target){
            target = r;
        }else{
            for(var i in this.players){
                if(this.players[i].id == targetid){
                    target = this.players[i];
                    break;
                }
            }
        }

        if(target == null){
            console.log('outcards failed on invalid targetid -> '+targetid);
            return;
        }

        var srcchanger=uk.create_changer();
        var tagchanger=uk.create_changer();
        /**扣除消耗 */
        for(var i in c.cost){
            if(r.props[i] < c.cost[i]){
                console.log(r.name+'出牌失败，'+uk.get_prop_name(i)+'不足');
                return;
            }
            srcchanger.change_prop(i,-c.cost[i]);
        }
        for(var i in c.cost)
            r.props[i] -= c.cost[i];

        if(!r.on_action(uk.events.DO_OUTCARD,uk.event_status.BEFORE,r,srcchanger)
        || !target.on_action(uk.events.ON_OUTCARD,uk.event_status.BEFORE,r,tagchanger)){
            /** 此牌功用被跳过 */
            if(srcchanger.changed())
                this.broadcast(uk.netevents.PROPCHANGE,{id:r.id,changed:srcchanger.value()});
            if(tagchanger.changed())
                this.broadcast(uk.netevents.PROPCHANGE,{id:target.id,changed:tagchanger.value()});
            this.broadcast(uk.netevents.OUTCARD,{success:true,id:r.id,card:c,targetid:targetid});
            return;
        }

        r.on_action(uk.events.DO_OUTCARD,uk.event_status.NOW,r,srcchanger);
        target.on_action(uk.events.ON_OUTCARD,uk.event_status.NOW,r,tagchanger);
        c.action(r,target,tagchanger);

        /** 移除牌 */
        var c = r.handcards[cpos];
        r.handcards.splice(cpos,1);
        this.deskcards.push(c);
        this.broadcast(uk.netevents.OUTCARD,{success:true,id:r.id,card:c,targetid:targetid});

        r.on_action(uk.events.DO_OUTCARD,uk.event_status.AFTER,r,srcchanger);
        target.on_action(uk.events.ON_OUTCARD,uk.event_status.AFTER,r,tagchanger);

        if(srcchanger.changed())
            this.broadcast(uk.netevents.PROPCHANGE,{id:r.id,changed:srcchanger.value()});
        if(tagchanger.changed())
            this.broadcast(uk.netevents.PROPCHANGE,{id:target.id,changed:tagchanger.value()});

        if(target.props.hp <= 0||r.props.hp <= 0){
            var anyenemy = false;
            for(var i in this.players){
                var _r = this.players[i];
                if(_r == null) continue;
                if(_r.team != r.team && _r.props.hp > 0){
                    anyenemy = true;
                    break;
                }
            }
            if(!anyenemy){
                this.game_end();
                return;
            }
        }

        if(uk.ismonster(r) && r.handcards.length == 0){
            this.finish_round();
        }
    }

    /**结束回合 */
    room.finish_round=function(){
        if(this.timer != null){
            uk.stop_timer(this.timer);
            this.timer = null;
        }
        if(this.status != uk.room_status.INGAME)
            return;
        this.player_turn(this.next_turn(this.whoturn));
    }

    room.dismiss=function(neednotify){
        if(this.timer != null){
            uk.stop_timer(this.timer);
            this.timer = null;
        }
        this.status = uk.room_status.END;
        for(var r in this.players){
            /**不需要通知客户端 */
            this.player_leave(this.players[i],!neednotify);
        }
    }

    /**结算成绩 */
    room.calc_game_scores=function(){        
        var dropadd = uk.create_changer();
        for(var i in this.players){
            var r = this.players[i];
            if(r==null) continue;
            if(uk.ismonster(r) && r.props.hp <= 0){
                for(var k in r.dropitem){
                    var di = r.dropitem[k];
                    var chance = uk.rand(0,10000)/10000.0;
                    if(chance >= di.chance)
                        continue;
                    var n = (typeof di.val == 'number')?di.val:uk.rand(di.val[0],di.val[1]);
                    dropadd.change_prop(di.id,n);
                }
            }
        }

        if(dropadd.changed()){
            /**这里单纯的给每个玩家都加上，有联机模式时必须要考虑胜利者及经验算法 */
            var dropvals = dropadd.value();
            for(var i in this.players){
                var r = this.players[i];
                if(r==null) continue;
                if(!uk.ismonster(r)){
                    var gamescore = uk.create_changer();
                    uk.actions.change_props(r,r,dropvals.props,gamescore);
                    if(gamescore.changed()){
                        this.broadcast(uk.netevents.PROPCHANGE,{id:r.id,changed:gamescore.value()});
                    }
                }
            }
        }
    }

    room.player_count=function(onlyplayer=false){
        var c = 0;
        for(var i in this.players){
            if(this.players[i] != null){
                c += onlyplayer&&uk.ismonster(this.players[i])?0:1;
            }
        }
        return c;
    }

    room.reset_player_data=function(r,changed){
        /** buff需要移除 */
        var c = changed?changed:uk.create_changer();
        for(var i = 0;i < r.buffs.length;){
            var b = r.buffs[i];
            if(b.template.type & uk.buff_types.PERPETUAL){/**非永久性的才移除 */
                ++i;
            }else{
                uk.actions.del_buff_byindex(r,r,i,c);
            }
        }
        if(!changed && c.changed()){
            this.send(r,uk.netevents.PROPCHANGE,{id:r.id,changed:c.value()});
        }
    }

    room.players = [];      /** 玩家 */
    room.deskcards = [];    /** 桌面上的牌 */
    room.timer = null;
    room.status = uk.room_status.NONE;
    room.winner = [];

    var monsterroom = uk.room_types.MONSTER==station.type;
    var pcount = monsterroom?station.playercount+1:station.playercount;
    for(var i = 0;i < pcount;++i){
        room.players.push(null);
    }

    /**怪物，直接放进去 */
    if(monsterroom){
        var npc = uk.create_role(station.monster);
        npc.id = uk.getnewguidn();
        if(station.cards){
            for(var i in station.cards){
                if(npc.cards[i]) npc.cards[i] += station.cards[i];
                else npc.cards[i] = station.cards[i];
            }
        }
        room.player_enter(npc,-1);
        room.player_start(npc);
    }

    console.log('room create:',room.players.length,monsterroom,room.status);
    return room;
}